<template>
    <view
        class="tui-swipeout-wrap"
        :style="{ backgroundColor: backgroundColor }"
    >
        <view
            class="tui-swipeout-item"
            :class="[isShowBtn ? 'swipe-action-show' : '']"
            @touchstart="handlerTouchstart"
            @touchmove="handlerTouchmove"
            @touchend="handlerTouchend"
            @mousedown="handlerTouchstart"
            @mousemove="handlerTouchmove"
            @mouseup="handlerTouchend"
            :style="{ transform: 'translate(' + position.pageX + 'px,0)' }"
        >
            <view class="tui-swipeout-content">
                <slot name="content"></slot>
            </view>
            <view
                class="tui-swipeout-button-right-group"
                v-if="actions.length > 0"
                @touchend.stop="loop"
            >
                <view
                    class="tui-swipeout-button-right-item"
                    v-for="(item, index) in actions"
                    :key="index"
                    :style="{
                        borderRadius: px(item.borderRadius),
                        backgroundColor: item.background || '#f7f7f7',
                        color: item.color,
                        width: item.width + 'px'
                    }"
                    :data-index="index"
                    @tap="handlerButton"
                >
                    <image
                        :src="item.icon"
                        v-if="item.icon"
                        :style="{
                            width: px(item.imgWidth),
                            height: px(item.imgHeight)
                        }"
                    ></image>
                    <text :style="{ fontSize: px(item.fontsize) }">{{
                        item.name
                    }}</text>
                </view>
            </view>
            <!--actions长度设置为0，可直接传按钮进来-->
            <view
                class="tui-swipeout-button-right-group"
                @touchend.stop="loop"
                @tap="handlerParentButton"
                v-if="actions.length === 0"
                :style="{
                    width: operateWidth + 'px',
                    right: '-' + operateWidth + 'px'
                }"
            >
                <slot name="button"></slot>
            </view>
        </view>
        <view
            v-if="isShowBtn && showMask"
            class="swipe-action_mask"
            @tap.stop="closeButtonGroup"
            @touchstart.stop.prevent="closeButtonGroup"
        />
    </view>
</template>

<script>
export default {
    name: 'tuiSwipeAction',
    props: {
        // name: '删除',
        // color: '#fff',
        // fontsize: 32,//单位rpx
        // width: 80, //单位px
        // icon: 'like.png',//此处为图片地址
        // background: '#ed3f14'
        actions: {
            type: Array,
            default() {
                return []
            }
        },
        //点击按钮时是否自动关闭
        closable: {
            type: Boolean,
            default: true
        },
        //设为false，可以滑动多行不关闭菜单
        showMask: {
            type: Boolean,
            default: true
        },
        operateWidth: {
            type: Number,
            default: 80
        },
        params: {
            type: Object,
            default() {
                return {}
            }
        },
        //禁止滑动
        forbid: {
            type: Boolean,
            default: false
        },
        //手动开关
        open: {
            type: Boolean,
            default: false
        },
        //背景色
        backgroundColor: {
            type: String,
            default: '#fff'
        },
        // swipe插入的内容
        content: {
            type: Object,
            required: false
        }
    },
    watch: {
        actions(newValue, oldValue) {
            this.updateButtonSize()
        },
        open(newValue) {
            this.manualSwitch(newValue)
        }
    },
    data() {
        return {
            //start position
            tStart: {
                pageX: 0,
                pageY: 0
            },
            //限制滑动距离
            limitMove: 0,
            //move position
            position: {
                pageX: 0,
                pageY: 0
            },
            isShowBtn: false,
            move: false
        }
    },
    mounted() {
        this.updateButtonSize()
    },
    methods: {
        swipeDirection(x1, x2, y1, y2) {
            return Math.abs(x1 - x2) >= Math.abs(y1 - y2)
                ? x1 - x2 > 0
                    ? 'Left'
                    : 'Right'
                : y1 - y2 > 0
                ? 'Up'
                : 'Down'
        },
        //阻止事件冒泡
        loop() {},
        updateButtonSize() {
            const actions = this.actions
            if (actions.length > 0) {
                const query = uni.createSelectorQuery().in(this)
                let limitMovePosition = 0
                actions.forEach(item => {
                    limitMovePosition += item.width || 0
                })
                this.limitMove = limitMovePosition
            } else {
                this.limitMove = this.operateWidth
            }
        },
        handlerTouchstart(event) {
            if (this.forbid) return
            let touches = event.touches
            if (touches && touches.length > 1) return
            this.move = true
            touches = touches ? event.touches[0] : {}
            if (
                !touches ||
                (touches.pageX === undefined && touches.pageY === undefined)
            ) {
                touches = {
                    pageX: event.pageX,
                    pageY: event.pageY
                }
            }
            const tStart = this.tStart
            if (touches) {
                for (let i in tStart) {
                    if (touches[i]) {
                        tStart[i] = touches[i]
                    }
                }
            }
        },
        swipper(touches) {
            const start = this.tStart
            const spacing = {
                pageX: touches.pageX - start.pageX,
                pageY: touches.pageY - start.pageY
            }
            if (this.limitMove < Math.abs(spacing.pageX)) {
                spacing.pageX = -this.limitMove
            }
            this.position = spacing
        },
        handlerTouchmove(event) {
            if (this.forbid || !this.move) return
            const start = this.tStart
            let touches = event.touches ? event.touches[0] : {}
            if (
                !touches ||
                (touches.pageX === undefined && touches.pageY === undefined)
            ) {
                touches = {
                    pageX: event.pageX,
                    pageY: event.pageY
                }
            }
            if (touches) {
                const direction = this.swipeDirection(
                    start.pageX,
                    touches.pageX,
                    start.pageY,
                    touches.pageY
                )
                if (
                    direction === 'Left' &&
                    Math.abs(this.position.pageX) !== this.limitMove
                ) {
                    this.swipper(touches)
                }
            }
        },
        handlerTouchend(event) {
            if (this.forbid || !this.move) return
            this.move = false
            const start = this.tStart
            let touches = event.changedTouches ? event.changedTouches[0] : {}
            if (
                !touches ||
                (touches.pageX === undefined && touches.pageY === undefined)
            ) {
                touches = {
                    pageX: event.pageX,
                    pageY: event.pageY
                }
            }
            if (touches) {
                const direction = this.swipeDirection(
                    start.pageX,
                    touches.pageX,
                    start.pageY,
                    touches.pageY
                )
                const spacing = {
                    pageX: touches.pageX - start.pageX,
                    pageY: touches.pageY - start.pageY
                }
                if (Math.abs(spacing.pageX) >= 40 && direction === 'Left') {
                    spacing.pageX =
                        spacing.pageX < 0 ? -this.limitMove : this.limitMove
                    this.isShowBtn = true
                } else {
                    spacing.pageX = 0
                }
                this.position = spacing
            }
        },
        handlerButton(event) {
            if (this.closable) {
                this.closeButtonGroup()
            }
            const dataset = event.currentTarget.dataset
            this.$emit('selected', {
                index: Number(dataset.index),
                item: this.params,
                content: this.content
            })
        },
        closeButtonGroup() {
            this.position = {
                pageX: 0,
                pageY: 0
            }
            this.isShowBtn = false
        },
        //控制自定义按钮菜单
        handlerParentButton(event) {
            if (this.closable) {
                this.closeButtonGroup()
            }
        },
        manualSwitch(isOpen) {
            let x = 0
            if (isOpen) {
                if (this.actions.length === 0) {
                    x = this.operateWidth
                } else {
                    let width = 0
                    this.actions.forEach(item => {
                        width += item.width
                    })
                    x = width
                }
            }
            this.position = {
                pageX: -x,
                pageY: 0
            }
        },
        px(num) {
            return uni.upx2px(num) + 'px'
        }
    }
}
</script>

<style scoped>
.tui-swipeout-wrap {
    position: relative;
    overflow: hidden;
}

.swipe-action-show {
    position: relative;
    z-index: 998;
}

.tui-swipeout-item {
    width: 100%;
    /* padding: 15px 20px; */
    box-sizing: border-box;
    transition: transform 0.2s ease;
    font-size: 14px;
    cursor: pointer;
}

.tui-swipeout-content {
    overflow: hidden;
}

.tui-swipeout-button-right-group {
    position: absolute;
    right: -100%;
    top: 0;
    height: 100%;
    z-index: 1;
    width: 100%;
}

.tui-swipeout-button-right-item {
    height: 100%;
    float: left;
    white-space: nowrap;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

.swipe-action_mask {
    display: block;
    opacity: 0;
    position: fixed;
    z-index: 997;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
</style>
